package eg.ci.mvn.service.demo.facade;


import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.ToIntBiFunction;

import static eg.ci.mvn.service.api.model.param.ParkingCardParam.AccessRule;
import static eg.ci.mvn.service.api.model.param.ParkingCardParam.CardGroup;
import static eg.ci.mvn.service.api.model.param.ParkingParam.ParkingSignalParam;

/**
 * 卡证(不同类型优先级 黑名单 > 临停 > 白名单 > 访客 > 月卡)
 */
@Component
public class AccessCtrlServiceFacade {


    /**
     * 日历判定
     */
    private final BiPredicate<AccessRule, ParkingSignalParam> calendarPredicate = (rule, signal) -> true;
    /**
     * 颜色判定
     */
    private final BiPredicate<AccessRule, ParkingSignalParam> colorPredicate = (rule, signal) -> true;
    /**
     * 开始时间判定
     */
    private final BiPredicate<AccessRule, ParkingSignalParam> startTimePredicate = (rule, signal) -> true;
    /**
     * 结束时间判定
     */
    private final BiPredicate<AccessRule, ParkingSignalParam> endTimePredicate = (rule, signal) -> true;

    /**
     * AccessRule 全组合判定
     */
    private final BiPredicate<AccessRule, ParkingSignalParam> allPredicate = calendarPredicate.and(colorPredicate).and(startTimePredicate).and(endTimePredicate);

    // 通行类型标志 0-无限制 1-禁止通过 2-允许通过 3-弹框确认
    private final ToIntBiFunction<AccessRule, ParkingSignalParam> toAccessRuleType = (rule, signal) -> 0;

    /**
     * 卡证判定
     */
    private final BiPredicate<CardGroup, ParkingSignalParam> cardToAccessRuleType = (cardGroup, signal) -> true;

    /**
     * 通行类型标志 0-无限制 1-禁止通过 2-允许通过 3-弹框确认
     *
     * @param cards
     * @param signal
     * @return
     */
    public Integer access(List<CardGroup> cards, ParkingSignalParam signal) {

        // 卡证【不同类型优先级 黑名单(默认不通过) > 临停(默认弹窗) > 白名单(默认通过) > 访客(默认通过) > 月卡(默认通过)】

        // 过滤首个符合的规则
        AccessRule rule = cards.stream()
                // 过滤空值
                .filter(it -> Objects.nonNull(it))
                // 过滤空值
                .filter(it -> Objects.nonNull(it.getAccessRules()))
                // List<AccessRule> 转换为 流 Stream<AccessRule>
                .flatMap(it -> it.getAccessRules().stream())
                // Predicate 过滤
                .filter(accessRule -> allPredicate.test(accessRule, signal))
                // 查找首个匹配项
                .findFirst().orElse(null);

        //
        return toAccessRuleType.applyAsInt(rule, signal);
    }
}
